
#include "debug.h"
#include "video.h"
#include "fileio.h"

#include <stdio.h>
#include <stdlib.h>

#include <fcntl.h>
#include <unistd.h>

#include <linux/videodev2.h>

#include <sys/ioctl.h>

//#define JPEG_HARD_ENCODING			1

//#if V4L2_FORMAT == V4L2_PIX_FMT_RGB32
	#define HEAD_RGB32					1
//#elif V4L2_FORMAT == V4L2_PIX_FMT_RGB565
//	#define HEAD_RGB565					1
//#endif

static char bmphead[54] = {
#ifdef HEAD_RGB565
	0x42, 0x4D,
	0x36, 0xB0, 0x04, 0x00,		// 文件大小
	0x00, 0x00, 0x00, 0x00,		// 保留
	0x36, 0x00, 0x00, 0x00,		// 图像数据偏移
	0x28, 0x00, 0x00, 0x00,		// 头长度
	0x80, 0x02, 0x00, 0x00,		// 宽: 0x280(640)
	0xE0, 0x01, 0x00, 0x00,		// 宽: 0x1E0(480)
	0x01, 0x00,					// 图层
	0x10, 0x00,					// 像素位宽, 16位
	0x00, 0x00, 0x00, 0x00,		// 保留
	0x00, 0xB0, 0x04, 0x00,		// 图像数据长度
#endif
#ifdef HEAD_RGB32
	0x42, 0x4D,
	0x36, 0xC0, 0x12, 0x00,		// 文件大小
	0x00, 0x00, 0x00, 0x00,		// 保留
	0x36, 0x00, 0x00, 0x00,		// 图像数据偏移
	0x28, 0x00, 0x00, 0x00,		// 头长度
	0x80, 0x02, 0x00, 0x00,		// 宽: 0x280(640)
	0xE0, 0x01, 0x00, 0x00,		// 宽: 0x1E0(480)
	0x01, 0x00,					// 图层
	0x20, 0x00,					// 像素位宽, 32位
	0x00, 0x00, 0x00, 0x00,		// 保留
	0x00, 0xC0, 0x12, 0x00,		// 图像数据长度
#endif
	0x00, 0x00, 0x00, 0x00,		// 其他参数
	0x00, 0x00, 0x00, 0x00,		// 其他参数
	0x00, 0x00, 0x00, 0x00,		// 其他参数
	0x00, 0x00, 0x00, 0x00		// 其他其他参数
};

static int save_file(struct camera_class *cam, void *start, uint32_t length, char *path)
{
#ifdef JPEG_HARD_ENCODING
	return 0;
#else
	char buffer_path[256] = {0};
	snprintf(buffer_path, sizeof(buffer_path), "%s/test.bmp", path);
	
	return save_to_file(buffer_path, bmphead, sizeof(bmphead), start, length);
#endif
}

int main(int argc, char **argv)
{
#ifdef V4L2_FORMAT
	int ret = 0;
#ifdef VIDEO_SWITCH
	int sfd = 0;
#endif

	struct camera_class *cam = NULL;

#ifdef VIDEO_SWITCH
	if(6 != argc)
#else
	if(5 != argc)
#endif
	{
#ifdef VIDEO_SWITCH
		printf("Usage: %s [DEVICE] [CHANNEL] [WIDTH] [HEIGHT] [CAMID]\n", argv[0]);
#else
		printf("Usage: %s [DEVICE] [CHANNEL] [WIDTH] [HEIGHT]\n", argv[0]);
#endif
		ret = -1;
		goto free;
	}

	INF_DUMP("Program start...");
	
#ifdef VIDEO_SWITCH
	INF_DUMP("Args: %s, %s, %s, %s, %s, It's correct?\nPress any key to continue...\n", argv[1], argv[2], argv[3], argv[4], argv[5]);
#else
	INF_DUMP("Args: %s, %s, %s, %s, It's correct?\nPress any key to continue...\n", argv[1], argv[2], argv[3], argv[4]);
#endif

	getchar();

#ifdef VIDEO_SWITCH
	sfd = open("/dev/cam_select", O_RDWR);
	if(0 <= sfd)
	{
		ioctl(sfd, atoi(argv[5]), 0);
		close(sfd);
	}
	else
	{
		ERR_DUMP("open()");
		ret = -1;
		goto free;
	}
#endif
	
	cam = video_init(argv[1], atoi(argv[2]), atoi(argv[3]), atoi(argv[4]), V4L2_FORMAT);

	if(NULL == cam)
	{
		ERR_DUMP("video_init()");
		ret = -1;
		goto free;
	}

	INF_DUMP("Object create success");
	
	if(0 != cam->auto_config(cam, 4, CAMERA_MODE_S_G))
	{
		ERR_DUMP("auto_config()");
		ret = -1;
		goto free;
	}

	INF_DUMP("Camera init success");

	if(0 != cam->start_stream(cam))
	{
		ERR_DUMP("start_stream()");
		ret = -1;
		goto free;
	}

	INF_DUMP("Camera start streaming");

	if(0 != cam->ignore_frame(cam, 1, 50))
	{
		ERR_DUMP("ignore_frame()");
		ret = -1;
		goto free;
	}

	INF_DUMP("Camera ignore frame finish");

#ifdef VIDEO_LOOP_SAVE
	while(1)
	{
#endif

		if(0 != cam->get_frame(cam, 3))
		{
			ERR_DUMP("get_frame()");
			ret = -1;
			goto free;
		}

		INF_DUMP("Camera get frame finish");

		if(0 != cam->pop_buf(cam))
		{
			ERR_DUMP("pop_buf()");
			ret = -1;
			goto free;
		}

		INF_DUMP("Camera pop buffer finish");
		
		INF_DUMP("Save to file, size = 0x%08X", cam->buf[cam->active_buf_index].length);
		save_file(cam, cam->buf[cam->active_buf_index].start, cam->buf[cam->active_buf_index].length, (char *)"/tmp");

		if(0 != cam->push_buf(cam))
		{
			ERR_DUMP("push_buf()");
			ret = -1;
			goto free;
		}

		INF_DUMP("Camera push buffer finish");

#ifdef VIDEO_LOOP_SAVE
	}
#endif

	if(0 != cam->stop_stream(cam))
	{
		ERR_DUMP("start_stream()");
		ret = -1;
		goto free;
	}

	INF_DUMP("Camera stop streaming");

	INF_DUMP("Everything is OK");

free:
	INF_DUMP("Program release start");

	if(NULL != cam)
	{
		cam->release(&cam);
	}

	INF_DUMP("Program release complete");

	return ret;
#else
#error $ No Format Select $
#endif
}